#include "../sysdef.h"

//WB_STA_WPA_DESCRIPTION Global_STA_Wpa;
//pWB_STA_WPA_DESCRIPTION pGlobal_STA_Wpa = &Global_STA_Wpa;
//extern void* pAdapterContext;
//static PWB32_ADAPTER pAdapter=NULL;//(PWB32_ADAPTER)pAdapterContext;
//static pWB_STA_WPA_DESCRIPTION pGlobal_STA_Wpa=NULL;//&pAdapter->Global_STA_Wpa;
//static STATION* STA=NULL;
//#define  pAdapter PWB32_ADAPTER


//-------------------------------------------------------------------------//
/*
typedef struct _AlignmentStruct_{

	u8  TestChar;
	u16 TestShort;
	u32  TestLong;
	
}__attribute__ ((packed)) AlignmentStruct;
*/
//-------------------------------------------------------------------------//
//Initalize
void FourWayInit(void* DeviceHandle)
{
	//pAdapter=(PWB32_ADAPTER)DeviceHandle;
	//pGlobal_STA_Wpa=&pAdapter->Global_STA_Wpa;
	//STA = &pGlobal_STA_Wpa->WPA_STA;
	
	PWB32_ADAPTER Adapter=(PWB32_ADAPTER)DeviceHandle;
	//To get the current encryption status
	//pGlobal_STA_Wpa->EncryptionMode = psSME->encrypt_status;
	//memcpy(pGlobal_STA_Wpa->WPAPassword, "12345678", 8);
	memcpy(pGlobal_STA_Wpa->AdapterMAddress, Adapter->sLocalPara.ThisMacAddress, MAC_ADDR_LENGTH);
	
	//For debug
#ifdef _WPA_PSK_DEBUG	
	WBDEBUG(("Station MacAddress\n"));
	DataDmp(Adapter->sLocalPara.ThisMacAddress, MAC_ADDR_LENGTH, 0);
#endif	
	
	OS_MEMORY_CLEAR(pSTA, sizeof(STATION));
	pSTA->PMK.m_OnStep= FWayStep2;
}

void FourWayClear(void* DeviceHandle)
{
	
	PWB32_ADAPTER Adapter=(PWB32_ADAPTER)DeviceHandle;
	Block32  PMK_TMP={0};
	#ifdef _WPA_PSK_DEBUG			
		WBDEBUG(("pGlobal_STA_WPA size = %d\n", sizeof(WB_STA_WPA_DESCRIPTION) ));
		WBDEBUG(("station size = %d\n", sizeof(STATION) ));
		WBDEBUG(("Pair Master Key size = %d\n", sizeof(PairMasterKey) ));
		WBDEBUG(("Group Master Key size = %d\n", sizeof(GroupMasterKey) ));
	#endif		
	
	if(pSTA)
	{
#ifdef _WPA_PSK_DEBUG			
		WBDEBUG(("4 way handshake clear\n"));
#endif		
		memcpy(PMK_TMP, pSTA->PMK.m_pmk, sizeof(Block32) );
		OS_MEMORY_CLEAR(pSTA, sizeof(STATION));
		memcpy( pSTA->PMK.m_pmk, PMK_TMP, sizeof(Block32) );
	#ifdef _WPA_PSK_DEBUG			
		WBDEBUG(("4 way handshake clear pmk = \n"));
		DataDmp(pSTA->PMK.m_pmk, 32 , 0);
	#endif		
		pSTA->PMK.m_OnStep =FWayStep2;
	}
}
//Added by WangJs 2005.11.12
void Start4WayStateMachine(void* DeviceHandle, u32 RecvPacketSize, void* RecvPacket, u32 SendPacketSize, void* SendPacket)
{
	//PWB32_ADAPTER pAdapter=(PWB32_ADAPTER)pAdapterContext;
	//pWB_STA_WPA_DESCRIPTION pGlobal_STA_Wpa=&pAdapter->Global_STA_Wpa;
	//STATION* STA = &pGlobal_STA_Wpa->WPA_STA;

	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)DeviceHandle;
	//MACAddress NullMACAddress={0x00,0x00,0x00,0x00,0x00,0x00};
	//Because the pairwise key and group key is not O.K
	//For test, for alignment
	/*
	AlignmentStruct* A1= memcpy(sizeof(AlignmentStruct));
	A1->TestChar  = 0x10;
	A1->TestShort = 0x1234;
	A1->TestLong = 0x56789a10;
	A1->TestShort |= 0x0101; 
	
	WBDEBUG((" A1.TestChar = %02x \n", A1->TestChar));
	WBDEBUG((" A1.TestShort = %04x \n", A1->TestShort));
	WBDEBUG((" A1.TestLong = %08x \n", A1->TestLong));
	//Display Address
	WBDEBUG((" A1.TestChar Address = 0x%x \n", &A1->TestChar));
	WBDEBUG((" A1.TestShort Address= 0x%x \n", &A1->TestShort));
	WBDEBUG((" A1.TestLong Address= 0x%x \n", &A1->TestLong));
	*/
	///////////////////////////////////////////////////////////////////

	FourWay_Get_Encryption_Status(Adapter, &pGlobal_STA_Wpa->EncryptionMode);
	//pGlobal_STA_Wpa->EncryptionMode = ENCRYPT_TKIP;
#ifdef _WPA_PSK_DEBUG		
	WBDEBUG(("EncryptionMode Mode =%d\n", pGlobal_STA_Wpa->EncryptionMode));
#endif	
	
	       

	if(pGlobal_STA_Wpa->EncryptionMode < ENCRYPT_TKIP)
	{
#ifdef _WPA_PSK_DEBUG			
		WBDEBUG(("No WPA Mode \n"));
#endif		
		return;
	}
	//For test

	//////////////////////////////////////////////////////////
	//Added by WangJS 2006.8.11
	if( CheckEAPType(Adapter, RecvPacket) == GROUP_FRAME_TYPE )
	{
		WBDEBUG(("Group Handshake Start\n"));
		pSTA->PMK.m_OnStep=STA_GHSSTtep2;
	}else
	{
		WBDEBUG(("Pairwise Handshake ReStart\n"));
		if(pSTA->PMK.m_OnStep == STA_GHSSTtep2)
			pSTA->PMK.m_OnStep=FWayStep2;
	}
	//////////////////////////////////////////////////////////
	switch(pSTA->PMK.m_OnStep)
	{
		
		case 0 :
			//Debug
			#ifdef _WPA_PSK_DEBUG	
			WBDEBUG(("4-way Step 0\n"));
			#endif
			pSTA->PMK.m_OnStep =FWayStep2;
			break;
		case FWayStep1:
			break;
		case FWayStep2:
			//Debug
			#ifdef _WPA_PSK_DEBUG	
			WBDEBUG(("4-way Step 2\n"));
			#endif
			AP_OnStep2(Adapter, pSTA, (PEAP_HEADER)RecvPacket, RecvPacketSize);
    		//STA->PMK.m_OnStep =FWayStep4;
			break;
		case FWayStep3:
			break;
		case FWayStep4:
			//Debug
			#ifdef _WPA_PSK_DEBUG	
			WBDEBUG(("4-way Step 4\n"));
			#endif
			
		    AP_OnStep4(Adapter, pSTA, (PEAP_HEADER)RecvPacket, RecvPacketSize);
			//Install the key
			//InstallKey(&STA->PMK.m_AA, &STA->PMK.m_tk1, &STA->PMK.m_tk2, (unsigned char)InstallPairwiseKey);
           	//STA->PMK.m_OnStep =STA_GHSSTtep2;
			break;
		case STA_GHSSTtep2:
			//Debug
			#ifdef _WPA_PSK_DEBUG	
			WBDEBUG(("group handshake Step 1\n"));
			#endif
			STA_OnGStep2(Adapter, pSTA, (PEAP_HEADER)RecvPacket, RecvPacketSize);
			//InstallKey(&STA->PMK.m_AA, &STA->GMP.m_gtk1, &STA->GMP.m_gtk2, (unsigned char)InstallGroupKey);
			//STA->PMK.m_OnStep =STA_MAX_COUNT;
			break;
		default:break;
	}
}

//-------------------------------------------------------------------------//
void AP_PasswordHash(void* DeviceHandle, /*const */u8* Password, Block32* PMK)
{
    
	u8 Buffer[256]={0};
	PWB32_ADAPTER Adapter=(PWB32_ADAPTER)DeviceHandle;

	u8* SSID=psSME->sDesiredSSID.SSID;//pGlobal_STA_Wpa->SSID;
	u32 SSIDLength= psSME->sDesiredSSID.Length;//strlen((char*)pGlobal_STA_Wpa->SSID);
	
	#ifdef _WPA_PSK_DEBUG	
		WBDEBUG(("(WangJS)AP_PasswordHash Password = %s\n",Password));
	#endif
    PasswordHash((u8*) Password, SSID, SSIDLength, Buffer);
	memcpy((void*)(*PMK), (void*)Buffer,32);
}


//Added by WangJS 2005.12.12
void AP_PrePasswordHash(void* DeviceHandle, u8* SSID, u8 SSIDLength)
{
	PWB32_ADAPTER Adapter=(PWB32_ADAPTER)DeviceHandle;
	u8* Password=pGlobal_STA_Wpa->WPAPassword;
	//u8* PMK=pSTA->PMK.m_pmk;
	u8 Buffer[256]={0};
		
	////////////////////////////////////////////////////////
	#ifdef _WPA_PSK_DEBUG	
	     WBDEBUG(("(WangJS)AP_PrePasswordHash Password = %s\n",Password));
	     WBDEBUG(("(WangJS)AP_PrePasswordHash SSID = %s\n",SSID));
	     WBDEBUG(("(WangJS)AP_PrePasswordHash SSID Length = %d\n",SSIDLength));
	#endif
	
	PasswordHash((u8*) Password, SSID, SSIDLength, Buffer);
	
	memcpy(pSTA->PMK.m_pmk, Buffer,32);
	#ifdef _WPA_PSK_DEBUG	
	     WBDEBUG(("(WangJS)AP_PrePasswordHash PMK =  \n"));
	     DataDmp(pSTA->PMK.m_pmk, 32, 0);
	#endif
	
	
}
//-------------------------------------------------------------------------//
unsigned char Is8021xPacket(u16 Type)
{
    return (unsigned char)(Type == EAPOL_802_1X_PACKET);
}


//-------------------------------------------------------------------------//
void AP_OnStep2(void* DeviceHandle, STATION* STA,/*PEAP_HEADER Eap*/void* Eap, u32 MessageSize)
{
	PWB32_ADAPTER Adapter=(PWB32_ADAPTER)DeviceHandle;
	
	PEAPOL_KEY EapolMessage = (PEAPOL_KEY)( (u8*)Eap + sizeof(ETH_PACKET) + sizeof(EAP_HEADER));
	PEAP_HEADER EapolKeyFrame = (PEAP_HEADER)((u8*)Eap + sizeof(ETH_PACKET));
	
	u32 TotalDataSize=0;
	u8 EapolFrame[1024]={0};

	//EAPOL_KEY EapolMessage;
	u8* Buffer=EapolFrame;
	u32 BufferSize=sizeof(EapolFrame);
	
	MACAddress m_AA, m_SA;
	Block32 m_ANonce, m_SNonce;
	//Block32 m_pmk;
//	Block8 NULLBlock8={0};
	Block16 NULLBlock16={0};
	u32 KeyDescVer = 0;    //To retrieve the mic algorithm version
	Block64 prf={0};

	//To get RSN element, added by WangJS 2005.9.28
	u8 RSN_IE[26]={0};//=pGlobal_AP->Ies.IesData;
	u32 RSNLength=26;//=pGlobal_AP->Ies.IesLen;
//	u8* WPAPassword=pGlobal_STA_Wpa->WPAPassword;
	//Bssid of AP
	//MACAddress Bssid={0x00,0x0D,0x88,0xC5,0x5A,0x53};
	MACAddress Bssid;//={0x00,0x10,0x1D,0x35,0x00,0xF9};
	//Added by WangJS 2006.7.26
//	phw_data_t pHwData=&(Adapter->sHwData);   
//	const u32 EapolFrameSize = sizeof(ETH_PACKET) + sizeof(EAP_HEADER) + sizeof(EAPOL_KEY) ;
   //----------------------------------
	//20061020 modified by anson
	//u32 EapolKeyFrameLength=MessageSize-sizeof(ETH_PACKET); //20061020 marked by anson
	u32 EapolKeyFrameLength;
	EapolKeyFrameLength=(u32)( be16_to_cpu( EapolKeyFrame->PBL ) + 4);  //4 = u8_version + u8_type + u16_length
	//----------------------------------	
	
								/*
								14 +	// 802.3 Protocol Type
								4 +    // 802.1x Header
								94 +    // EAPOL-Key descriptor length
								*/
	//For Alignment
	//Added by WangJS 2005.9.28

	
	////////////////////////////////////////////////////////////////////////
	//Added by WangJS 2006.7.26
	//hal_set_accept_promiscuous(pHwData,1);
	////////////////////////////////////////////////////////////////////////
	//To get the Bssid from SME
	memcpy(Bssid, CURRENT_BSSID, MAC_ADDR_LENGTH );
#ifdef _WPA_PSK_DEBUG	
	WBDEBUG(("AP MacAddress\n"));
	DataDmp(Bssid, MAC_ADDR_LENGTH, 0);
#endif	
	//MACAddress MacAddress={0x06,0x05,0x04,0x03,0x02,0x01};
	
	//To generate the Supplicant Nonce
	//For test, added by WangJS 2005.12.23
	TimeStamp("GenerateANonce 1st");
	
	GenerateANonce(&STA->PMK.m_SNonce);
	//For test, added by WangJS 2005.12.23
	TimeStamp("GenerateANonce 2nd");
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//To get the address of Authenticator
	memcpy(STA->PMK.m_AA, Bssid, MAC_ADDR_LENGTH);
	//To get the address of Supplicant
	memcpy(STA->PMK.m_SA, pGlobal_STA_Wpa->AdapterMAddress, MAC_ADDR_LENGTH);
	memcpy((void*)STA->PMK.m_ANonce ,(void*)EapolMessage->KeyNonce,sizeof(Block32));
	//memcpy((void*)STA->PMK.m_ReplayCounter ,(void*)EapolMessage->ReplayCounter,sizeof(Block8));
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	/////////////////////////////////////////////////////////////////////////////////////////
	
	//AP_PasswordHash(DeviceHandle, /*(unsigned char*)"12345678"*/WPAPassword, &m_pmk); //To test the password is "12345678"
	
	memcpy((void*)m_AA, (void*)STA->PMK.m_AA, MAC_ADDR_LENGTH);
	memcpy((void*)m_SA, (void*)STA->PMK.m_SA, MAC_ADDR_LENGTH);
	memcpy((void*)m_ANonce,(void*)EapolMessage->KeyNonce,sizeof(Block32));
	memcpy((void*)m_SNonce,STA->PMK.m_SNonce,sizeof(Block32));
	
	//.1)To Build EAPoL Frame
	//For test, added by WangJS 2005.12.23
	TimeStamp("GeneratePairwisePRF 1st");
	
	GeneratePairwisePRF(prf, &STA->PMK.m_pmk, &m_AA, &m_SA, &m_ANonce, &m_SNonce);
	
	//For test, added by WangJS 2005.12.23
	TimeStamp("GeneratePairwisePRF 2nd");
	
	
	memcpy(STA->PMK.m_mk, prf, 16);        //KCK generated
	memcpy(STA->PMK.m_ek, prf+16, 16);     //KEK genereted
	memcpy(STA->PMK.m_tk1, prf+32, 16);     //Temporal(1) key genereted
	memcpy(STA->PMK.m_tk2, prf+48, 16);     //Temporal(2) key genereted

	
		 
	//.3) 
	 
	 switch( pGlobal_STA_Wpa->EncryptionMode )
	 {
		case ENCRYPT_TKIP:
			KeyDescVer=1;
			break;
		case ENCRYPT_CCMP:
			KeyDescVer=2;
			break;
		default:
		#ifdef _WPA_PSK_DEBUG	
			WBDEBUG(("EncryptionMode Mode =%d\n", pGlobal_STA_Wpa->EncryptionMode));
		#endif	
			break;
	 }
	 
	//.4)To fill the Replay count, need to modify
	  //temporal write this
	
	  memcpy(STA->PMK.m_ReplayCounter, EapolMessage->ReplayCounter, 8);
	  memcpy(STA->PMK.m_KeyRSC, EapolMessage->KeyRSC, 8);
	  

	  //Parse the RSN IE, Added by WangJS 2005.10.4
	  
	  //For test, added by WangJS 2005.12.23
		TimeStamp("Supplicat_FillRSN 1st");
	  RSNLength = Supplicat_FillRSN(Adapter, RSN_IE, RSNLength);
	  //For test, added by WangJS 2005.12.23
		TimeStamp("Supplicat_FillRSN 2nd");
	  
	  if(RSNLength == 0) 
		  return;
		
	
	  /////////////////////////////////////////////////////////////////////////////////////////////////
	 

	  TotalDataSize=BuildEapolKeyMessage(Adapter, Buffer, BufferSize, &m_AA, &m_SA,  KeyDescVer, 
										 FALSE, TRUE, FALSE, TRUE ,FALSE, 0, &STA->PMK.m_ReplayCounter,
										 &STA->PMK.m_KeyRSC, &STA->PMK.m_SNonce, &STA->PMK.m_mk, &NULLBlock16, RSN_IE, 
										 RSNLength);
  #ifdef _WPA_PSK_DEBUG	
	//Send Packet Dump
	WBDEBUG(("(WangJS)Send Packet\n"));
	DataDmp(EapolFrame, TotalDataSize, 0);
  #endif	
	//4.)To send the EAPoL key to adapter
	 
	SendEAPoLPacket(Adapter, EapolFrame, TotalDataSize);
	
	
	//To clear the all EAPoL Frame,Added by WangJS 2005.10.12
	//OS_MEMORY_CLEAR(&STA->PMK.EAPoL_Packet, sizeof(EAPoL_PACKET));
	//To copy the EAPoL packet, Added by WangJS 2005.10.9
	//STA->PMK.EAPoL_Packet.TotalSize = TotalDataSize;
	
    //To retrieve the next PMK step
	STA->PMK.m_OnStep = FWayStep4;//4;

}


//-------------------------------------------------------------------------//
void AP_OnStep4(void* DeviceHandle, STATION* STA,/*PEAP_HEADER Eap*/void* Eap, u32 MessageSize)
{
    
	PEAPOL_KEY EapolMessage = (PEAPOL_KEY)((u8*)Eap + sizeof(ETH_PACKET) + sizeof(EAP_HEADER) );
	PEAP_HEADER EapolKeyFrame = (PEAP_HEADER)((u8*)Eap + sizeof(ETH_PACKET));
	//----------------------------------
	//20061020 modified by anson
	//u32 EapolKeyFrameLength=MessageSize-sizeof(ETH_PACKET); //20061020 marked by anson
	u32 EapolKeyFrameLength;

	//----------------------------------	

	const u32 EapolFrameSize = sizeof(ETH_PACKET) + sizeof(EAP_HEADER) + sizeof(EAPOL_KEY) ;
								/*
								14 +	// 802.3 Protocol Type
								4 +    // 802.1x Header
								95 +    // EAPOL-Key descriptor length
								*/
	//Added by WangJS 2005.12.7
	PWB32_ADAPTER Adapter=(PWB32_ADAPTER)DeviceHandle;
	//Added by WangJS 2005.9.28
	u32 TotalDataSize=0;
	u8 EapolFrame[1024]={0};

	//EAPOL_KEY EapolMessage;
	u8* Buffer=EapolFrame;
	u32 BufferSize=EapolFrameSize;
	
	MACAddress m_AA, m_SA;
	Block32 m_ANonce, m_SNonce;

	Block8 NULLBlock8={0};
	Block16 NULLBlock16={0};
	u32 KeyDescVer=0;    //To retrieve the mic algorithm version
	
	//Temp pairwise keys stoarage
	unsigned char PairwiseKeyIsOk;
	EapolKeyFrameLength=(u32)( be16_to_cpu(EapolKeyFrame->PBL ) + 4);  //4=u8_version + u8_type + u16_length

	memcpy((void*)m_AA, (void*)STA->PMK.m_AA, MAC_ADDR_LENGTH);
	memcpy((void*)m_SA, (void*)STA->PMK.m_SA, MAC_ADDR_LENGTH);
	memcpy((void*)m_ANonce,STA->PMK.m_ANonce,sizeof(Block32));
	memcpy((void*)m_SNonce,(void*)EapolMessage->KeyNonce,sizeof(Block32));
	

	//.1)To Build EAPoL Frame
	
	
	
	//.2)To check whether the Anounce is correct or not
	  if(memcmp(EapolMessage->KeyNonce,STA->PMK.m_ANonce,sizeof(Block32)) != 0)
	  {
		  #ifdef _WPA_PSK_DEBUG	
		  //The Anonce is incorrect
		    WBDEBUG(("Step 4 ANonce is different\n"));
		    WBDEBUG(("Message Nonuce\n"));
		    DataDmp(EapolMessage->KeyNonce, 32, 0);
		    WBDEBUG(("Station ANonuce\n"));
		    DataDmp(STA->PMK.m_ANonce, 32, 0);
		   #endif
		  return;
	  }
	//.3)To check whether the Replay is legal.
	  //Authenticator Replay Counter must be larger than original Replay Counter 
	  if( !Compare(EapolMessage->ReplayCounter, STA->PMK.m_ReplayCounter, sizeof(STA->PMK.m_ReplayCounter), 3) )
	  {
		  #ifdef _WPA_PSK_DEBUG	
		  //Fail to replay counter, the EapolMessage->ReplayCounter is too small
		  WBDEBUG(("Step 4 ReplayCount is error\n"));
 		 #endif 
		  return;
	  }
	
	  memcpy(STA->PMK.m_ReplayCounter, EapolMessage->ReplayCounter, 8);
	//.4)To check whether the MIC is correct or not
	
	 if( !KeyMICIsValid(Adapter, EapolKeyFrame, EapolKeyFrameLength, &EapolMessage->KeyMIC, &STA->PMK.m_mk) )
	 {
		 //MIC is fail
		 #ifdef _WPA_PSK_DEBUG	
		 WBDEBUG(("Step 4 MIC error\n"));
		 #endif
		 return;
	 }
	
	

	 switch( pGlobal_STA_Wpa->EncryptionMode )
	 {
		case ENCRYPT_TKIP:
			KeyDescVer=1;
			break;
		case ENCRYPT_CCMP:
			KeyDescVer=2;
			break;
		default:
			break;
	 }
	//.4)To fill the Replay count, need to modify

	  //temporal write this
	  //STA->PMK.m_ReplayCounter[7]=STA->PMK.m_ReplayCounter[0];
	
	
	  /////////////////////////////////////////////////////////////////////////////////////////////////
	 

	  TotalDataSize=BuildEapolKeyMessage(Adapter, Buffer, BufferSize, &m_AA, &m_SA,  KeyDescVer, 
										 FALSE, TRUE, FALSE, TRUE, FALSE, 0, &STA->PMK.m_ReplayCounter,
										 &NULLBlock8, &STA->PMK.m_SNonce, &STA->PMK.m_mk, &NULLBlock16, NULL, 
										 0);
  
		
	
	//It must be installed before send 4th packet of EAPoL packet
	//Install the Key
	InstallKey(Adapter, &STA->PMK.m_AA, &STA->PMK.m_tk1, &STA->PMK.m_tk2, (unsigned char)InstallPairwiseKey,0);
	///////////////////////////////////////////////////////////////////////
	//Added bsy wangJS 2006.7.10
	//Because of that installing key to set the "psSME->pairwise_key_ok" true.
	//If doing, it send EAPOL packet to be encrypted. We try to force to set the 
	//flag to false to disable the encryption ability.
	///////////////////////////////////////////////////////////////////////
	PairwiseKeyIsOk = psSME->pairwise_key_ok;
	//To force closing the pairwise key encryption
	psSME->pairwise_key_ok = FALSE;
	///////////////////////////////////////////////////////////////////////
	
	//4.)To send the EAPoL key to adapter
	SendEAPoLPacket(Adapter, EapolFrame, TotalDataSize);
		
	
	///////////////////////////////////////////////////////////////////////
	//Added by WangJS 2006.7.10
	//To restore the previous status
	///////////////////////////////////////////////////////////////////////
		psSME->pairwise_key_ok = PairwiseKeyIsOk;
	///////////////////////////////////////////////////////////////////////
	
	//To clear the all EAPoL Frame,Added by WangJS 2005.10.12
//	OS_MEMORY_CLEAR(&STA->PMK.EAPoL_Packet, sizeof(EAPoL_PACKET));
	//To copy the EAPoL packet, Added by WangJS 2005.10.9
//	STA->PMK.EAPoL_Packet.TotalSize = TotalDataSize;
	//memcpy(STA->PMK.EAPoL_Packet.EAPoLBuffer, EapolFrame, STA->PMK.EAPoL_Packet.TotalSize);
	
	
	
	//To retrieve the next PMK step
	STA->PMK.m_OnStep = STA_GHSSTtep2;//7
	
	
}

//-------------------------------------------------------------------------//
void STA_OnGStep2(void* DeviceHandle, STATION* STA, void* Eap, u32 MessageSize)
{
	//Modified by WangJS 2005.12.8, for Alignment
	PEAPOL_KEY EapolMessage = (PEAPOL_KEY)((u8*)Eap + sizeof(ETH_PACKET) + sizeof(EAP_HEADER) );
	PEAP_HEADER EapolKeyFrame = (PEAP_HEADER)((u8*)Eap + sizeof(ETH_PACKET));
	//----------------------------------
	//20061020 modified by anson
	//u32 EapolKeyFrameLength=MessageSize-sizeof(ETH_PACKET); //20061020 marked by anson
	u32 EapolKeyFrameLength;

	//----------------------------------	

	//Modified by WangJS 2005.12.8
	const u32 EapolFrameSize = sizeof(ETH_PACKET) + sizeof(EAP_HEADER) + sizeof(EAPOL_KEY);
								/*
								14 +	// 802.3 Protocol Type
								4 +    // 802.1x Header
								95 +    // EAPOL-Key descriptor length
								*/

	//Added by WangJS 2005.12.7
	PWB32_ADAPTER Adapter=(PWB32_ADAPTER)DeviceHandle;
	
	u8* KeyMaterial=(u8*)&EapolMessage[1];

	//Added by WangJS 2005.9.28
	u32 TotalDataSize=0;
	u8 EapolFrame[1024]={0};
	//Added by WangJS 2005.11.12
	u8 GroupDecryptKey[32]={0};
	u8 EncryptKey[32]={0};

	//EAPOL_KEY EapolMessage;
	u8* Buffer=EapolFrame;
	u32 BufferSize=EapolFrameSize;
	
		
	Block8     NULLBlock8={0};
	Block16    NULLBlock16={0};
	Block32    NULLBlock32={0};
	MACAddress NULLMacAddress={0};
	u32 KeyDescVer=0;    //To retrieve the mic algorithm version

	MACAddress m_AA, m_SA;
	Block32 m_ANonce, m_SNonce;
	//Added by WangJS 2005.12.15
	u16 AlignKeyMaterialLen;
	//Added by WangJS 2006.7.14
	u16 KeyIndex=0;
	//for test
	//Added by WangJS 2006.7.14
//	int testCount=0;
	EapolKeyFrameLength=(u32)( be16_to_cpu( EapolKeyFrame->PBL ) + 4);  //4 = u8_version + u8_type + u16_length	
	
	//Copy Address
	memcpy((void*)m_AA, (void*)STA->PMK.m_AA, MAC_ADDR_LENGTH);
	memcpy((void*)m_SA, (void*)STA->PMK.m_SA, MAC_ADDR_LENGTH);
	memcpy((void*)m_ANonce,STA->PMK.m_ANonce,sizeof(Block32));
	memcpy((void*)m_SNonce,(void*)EapolMessage->KeyNonce,sizeof(Block32));
	
	//.....................................................
	

	//.2)To check whether the Anounce is correct or not
	/*
	  if(memcmp(EapolMessage->KeyNonce,STA->PMK.m_ANonce,sizeof(Block32)) != 0)
	  {
		  //The Anonce is incorrect
		  WBDEBUG(("ANonnuce"));
		  return;
	  }
	  */
	//.3)To check whether the Replay is legal.
	 if( !Compare(EapolMessage->ReplayCounter, STA->PMK.m_ReplayCounter, sizeof(STA->PMK.m_ReplayCounter), 3) )
	  {
		  //Fail to replay counter, the EapolMessage->ReplayCounter is too small
		 #ifdef _WPA_PSK_DEBUG	 
		  WBDEBUG(("group handshake ReplayCount is error\n"));
		 #endif
		  return;
	  }

	  memcpy(STA->PMK.m_ReplayCounter, EapolMessage->ReplayCounter, 8);
	  #ifdef _WPA_PSK_DEBUG	
	  WBDEBUG(("Group Key Handshake\n"));
	  DataDmp(STA->PMK.m_ReplayCounter, 8 ,0);
	  #endif
	//.4)To check whether the MIC is correct or not
	
	 if( !KeyMICIsValid(Adapter, EapolKeyFrame, EapolKeyFrameLength, &EapolMessage->KeyMIC, &STA->PMK.m_mk) )
	 {
		 //MIC is fail
		 #ifdef _WPA_PSK_DEBUG	
		 WBDEBUG(("group handshake MIC error\n"));
		 #endif
		 return;
	 }
	
	 //Copy the Key IV
	 memcpy(STA->PMK.m_KeyIV, EapolMessage->KeyIV, sizeof(Block16) );
	 //CpuWord(&EapolMessage->KeyMaterialLen);
	 EapolMessage->KeyMaterialLen = be16_to_cpu(EapolMessage->KeyMaterialLen);  //20061011 anson's endian
	 //Added by WangJS 2005.12.15
	  AlignKeyMaterialLen=0;
	  memcpy(&AlignKeyMaterialLen, &EapolMessage->KeyMaterialLen, sizeof(u16) );
	 	 
	 
	 //To decrypt the key
	 //Added by WangJS 2005.11.12
	 switch( pGlobal_STA_Wpa->EncryptionMode )
	 {
		case ENCRYPT_TKIP:
						
			//copy encrypt key to temp buffer
			//Added by WangJS 2005.11.12
			memcpy(GroupDecryptKey, KeyMaterial, EapolMessage->KeyMaterialLen);
			memcpy(EncryptKey, STA->PMK.m_KeyIV,16);
			memcpy(EncryptKey+16, STA->PMK.m_ek,16);
			
			
			if(/*EapolMessage->KeyMaterialLen*/AlignKeyMaterialLen != 32)
				return;
			
			rc4_skip(EncryptKey, sizeof(EncryptKey), 256, GroupDecryptKey, EapolMessage->KeyMaterialLen);
			//To retrieve key
			memcpy(STA->GMP.m_gtk1, GroupDecryptKey, 16);
			memcpy(STA->GMP.m_gtk2, GroupDecryptKey+16, 16);

			KeyDescVer=1;
			break;

		case ENCRYPT_CCMP:
			if(/*EapolMessage->KeyMaterialLen*/AlignKeyMaterialLen != 24)
				return;

			aes_unwrap(STA->PMK.m_ek ,2 ,KeyMaterial ,GroupDecryptKey);
			//To install the Key
			memcpy(STA->GMP.m_gtk1, GroupDecryptKey, 16);

			KeyDescVer=2;
			break;
		default:
			break;
	 }
	
	 //////////////////////////////////////////////////////////////////////////////////////
	 //Added by WangJS 2006.7.13
	 //////////////////////////////////////////////////////////////////////////////////////
	 //To get the Key Index
	 KeyIndex=EapolMessage->KeyInfo;
	 //WBDEBUG(("KeyIndex =%x\n",KeyIndex));
	 //CpuWord(&KeyIndex);
	 KeyIndex = be16_to_cpu( KeyIndex );  //20061011 anson's endian
	 
	 //WBDEBUG(("KeyIndex<2> =%x\n",KeyIndex));
	 KeyIndex=(KeyIndex&(BIT(4) | BIT(5))) >> 4;
	 //WBDEBUG(("KeyIndex<3> =%x\n",KeyIndex));	 
	 
	 //Install group Key
	 InstallKey(Adapter, &NULLMacAddress, &STA->GMP.m_gtk1, &STA->GMP.m_gtk2, (unsigned char)InstallGroupKey, KeyIndex);
	 
	
	 //To send the last packet
	 TotalDataSize=BuildEapolKeyMessage(Adapter, Buffer, BufferSize, &m_AA, &m_SA,  KeyDescVer, 
										 TRUE, TRUE, FALSE, FALSE, FALSE, KeyIndex, &STA->PMK.m_ReplayCounter,
										 &NULLBlock8, &NULLBlock32, &STA->PMK.m_mk, &NULLBlock16, NULL, 
										 0);
  
	//4.)To send the EAPoL key to adapter
	SendEAPoLPacket(Adapter, EapolFrame, TotalDataSize);
	 //////////////////////////////////////////////////////////////////////////////////////

	 
	//Added by WangJS 2006.7.10
	WBDEBUG(("To send 2nd packet of group key\n"));
	WBDEBUG(("2nd group key, size = %d\n",TotalDataSize));
	#if 0
	//For test
	////////////////////////////////////////////////////////////////
	for(testCount=0;testCount<TotalDataSize;testCount++)
	{
		WBDEBUG(("%02x ",EapolFrame[testCount]));
	}
	WBDEBUG(("\n"));
	////////////////////////////////////////////////////////////////
	#endif
	//marked by wangJS 2005.12.9
	//STA->PMK.m_OnStep =STA_MAX_COUNT;
	//Added by WangJS 2005.12.9
	//FourWayClear(Adapter);
	
	 
}
//-------------------------------------------------------------------------//
void GenerateANonce(Block32* KeyNonceSeed)
{
    //unsigned char temp[32];
	//The Nonce Seed is 32 bytes length
	u32 i;
	u32 CurrentTime;
	u32* Seed = (u32*)(*KeyNonceSeed);
	//To get the current time
		//marked by WangJS 2005.12.26
	//OS_TIMER_GET_SYS_TIME(&CurrentTime);
		//Added by WangJS 2005.12.26
	OS_TIMER_GET_SYS_TIME( &CurrentTime ); // 20060802

	srand( (u32)CurrentTime);
	for (i=0; i < (sizeof(Block32)/sizeof(u32)); i++)
	{
		//temp=*((unsigned int*)(&KeyNonceSeed + i * 2)) = rand();
		Seed[i]  = rand();
	}

	
}

//-------------------------------------------------------------------------//
void GeneratePairwisePRF(u8* PairwisePRF,
						 Block32*		  pmk, 
						 MACAddress*	  AA, 
						 MACAddress*	  SA, 
						 Block32*		  ANonce, 
						 Block32*		  SNonce)
{
    // AA + SA + ANonce + SNonce
    //const int Size = 6 + 6 + 32 + 32;

    
	u8 prefix[] = "Pairwise key expansion";
	u32 prefix_len = strlen((char*)prefix);
    
    u8 data[PRFSize] = {0};
    u32 data_len = sizeof(data);
	u8 Buffer[128] = {0};
    u8* key = (u8*)(*pmk);
	
	//unsigned char* PairwisePRF=(unsigned char*)malloc(sizeof(Block64));
		
//Added by WangJS 2005.9.14	
	memcpy(data,     CompareMin((void*)(*AA), (void*)(*SA), MAC_ADDR_LENGTH), MAC_ADDR_LENGTH);
    memcpy(data + 6, CompareMax((void*)(*AA), (void*)(*SA), MAC_ADDR_LENGTH), MAC_ADDR_LENGTH);

    memcpy(data + 12, CompareMin((void*)(*ANonce), (void*)(*SNonce), 32), 32);
    memcpy(data + 44, CompareMax((void*)(*ANonce), (void*)(*SNonce), 32), 32);
	
	
    //PRF(const_cast<unsigned char*>(key), 32, prefix, prefix_len, data, data_len, Buffer, 4096);
	//Debug area
	#ifdef _WPA_PSK_DEBUG	
	WBDEBUG(("PRF Key\n"));
	DataDmp(key, 32, 0);
	WBDEBUG(("PRF Data\n"));
	DataDmp(data, data_len, 0);
	#endif
	
	
	PRF(key, 32, prefix, prefix_len, data, data_len, Buffer, sizeof(Buffer));

	#ifdef _WPA_PSK_DEBUG	
	WBDEBUG(("PRF\n"));
	DataDmp(Buffer, 64,0);
	#endif

	memcpy(PairwisePRF, Buffer,64);
	//memcpy(TestPairwisePRF, Buffer, 64);
	//For Test
	
    //return PairwisePRF(Buffer);
	//return (unsigned char*)PairwisePRF;
}


//****************************************************************************
//Function: To generate the Group Key PRF
//****************************************************************************

//****************************************************************************
//BuildEapolKeyMessage: To create the Eapol frame
//Buffer:        
//BufferSize:
//DA:              Destination Address
//SA:			   Source Address
//KeyDescVer:      The key descriptor of version
//bSecure:         to set the eapol frame secure type
//bMIC:            MIC value
//bResponse:       Need to response to this EAPoL frame
//bPairwise:       
//KeyIndex:
//ReplayCount:
//KeyRSC:
//KeyNonce:
//MK:
//KeyData:
//KeyDataSize:
//****************************************************************************
//-------------------------------------------------------------------------//
u32 BuildEapolKeyMessage(void* DeviceHandle, u8* Buffer, u32 BufferSize,
						  MACAddress* DA, MACAddress* SA, 
						  u32 KeyDescVer, unsigned char bSecure, unsigned char bMIC, unsigned char bResponse, 
						  unsigned char bPairwise,unsigned char bInstall, u32 KeyIndex,Block8* ReplayCount, Block8* KeyRSC, 
						  Block32* KeyNonce, Block16* MK, Block16* KeyIV,
						  u8* KeyData, u32 KeyDataSize)
{

	//const int S = sizeof(ETH_PACKET) + sizeof(EAP_HEADER) + sizeof(EAPOL_KEY);//14 + 4 + 95;
	
	//Added by WangJS 2005.9.28
	u32 TotalDataSize =sizeof(ETH_PACKET) + sizeof(EAP_HEADER) + sizeof(EAPOL_KEY);//14 + 4 + 95;
	
	//Added by WangJS 2005.12.6
	PWB32_ADAPTER Adapter=(PWB32_ADAPTER)DeviceHandle;

	//Added by WangJS 2005.9.15
	const u8* key;
	Block8 m_ReplayCounter;
	//For to calculate the MIC value, added by WangJS 2005.9.20
	u8 KeyMIC[1024] = {0};
	
	typedef void (*MIC_ALGO)(u8 *text, u32 text_len,
               u8 *key,  u32 key_len,
               u8 *digest);

	MIC_ALGO MicAlgo=0;
	
	PETH_PACKET EthHeader;
	PEAP_HEADER EapHeader;
	PEAPOL_KEY EapolKey;
	
	//Added by WangJS 2005.12.8
	u16 AlignTemp=0;
	u16 AlignDataSize=0;
	//Added by WangJs 2005.12.15
	u16 AlignKeyInfo=0;
	//////////////////////////////////////////////////////////////////////////////////
	//For test, Added by WangJS 2005.12.15
	#ifdef _WPA_PSK_DEBUG	
	   WBDEBUG(("Send Packet Address = (%08x)\n", Buffer));
	#endif
	
	OS_MEMORY_CLEAR(m_ReplayCounter, sizeof(m_ReplayCounter));

   // _ASSERT(BufferSize >= (S + KeyDataSize));

    OS_MEMORY_CLEAR(Buffer, BufferSize);



    // 802.3 Header
    EthHeader = (PETH_PACKET) Buffer;
    memcpy(EthHeader->DA, (*DA), MAC_ADDR_LENGTH);
    memcpy(EthHeader->SA, (*SA), MAC_ADDR_LENGTH);
    EthHeader->TL = cpu_to_le16(EAPOL_802_1X_PACKET);  //20061011 anson's endian
    Buffer += sizeof(ETH_PACKET);
    
    // 802.1x Header
    EapHeader = (PEAP_HEADER) Buffer; 
    EapHeader->PV = PV_EAPOL_1;                  //EAPoL version is "1"
    EapHeader->PT = PT_EAPOL_KEY;
    EapHeader->PBL = sizeof(EAPOL_KEY) + KeyDataSize;
    //CpuWord(&EapHeader->PBL);
    EapHeader->PBL = cpu_to_be16(EapHeader->PBL); //20061011 anson's endian
    Buffer += sizeof(EAP_HEADER);
    
    // EAPOL-Key message
    EapolKey = (PEAPOL_KEY) Buffer;
    
	///////////////////////////////////////////
	
    //marked by WangJS 2005.4.20
//    EapolKey->Desc = EAPOL_KEY_DESC_TYPE;
   //added by Sky 2005.4.20
/*
	if (m_Auth == GUI_802_11_AuthModeWPAPSK) // for wpa-psk
    EapolKey->Desc = EAPOL_KEY_DESC_TYPE;
    
	if (m_Auth == GUI_802_11_AuthModeWPA2PSK) 
		EapolKey->Desc = EAPOL_KEY_DESC_TYPE_WPA2; // sky add for wpa2-psk
 */  
	//Added b WangJS 2005.12.8
	EapolKey->Desc = EAPOL_KEY_DESC_TYPE;  //This is WPA version
	//marked by WangJS 2005.12.15
    	//EapolKey->KeyInfo = 0;
/*
    if (m_Encrypt == GUI_802_11_Encryption2Enabled)
    {
        EapolKey->KeyInfo |= EAPOL_KEY_INFO_VERSION_1;
        MicAlgo = ::hmac_md5;
    }
    else
    {
        EapolKey->KeyInfo |= EAPOL_KEY_INFO_VERSION_2;
        MicAlgo = ::hmac_sha1;
    }
*/
	//Temporally for TKIP
	switch(pGlobal_STA_Wpa->EncryptionMode)
	{
		case ENCRYPT_TKIP:
			//EapolKey->KeyInfo |= 1;
			AlignKeyInfo |= 1;
			break;
		case ENCRYPT_CCMP:
			//EapolKey->KeyInfo |= 2;
			AlignKeyInfo |= 2;
			break;
		default:
			break;
	}
	//***************************************************
	//Added by WangJS 2005.9.23
	//***************************************************
	if(bMIC)
	{
		switch(pGlobal_STA_Wpa->EncryptionMode)
		{
		case ENCRYPT_TKIP:
			 MicAlgo = hmac_md5;
			break;
		case ENCRYPT_CCMP:
			 MicAlgo = hmac_sha1;
			break;
		default:
			break;
		}
	}

    if (bPairwise)
        AlignKeyInfo |= BIT(3);//EapolKey->KeyInfo |= BIT(3);
	

    AlignKeyInfo |= (KeyIndex << 4 );//EapolKey->KeyInfo |= (KeyIndex << 4);
    
    
	//Added by WangJS 2005.9.29
	if (bInstall)
        	AlignKeyInfo |= BIT(6);//EapolKey->KeyInfo |= BIT(6);

	if (bResponse)
        	AlignKeyInfo |= BIT(7);//EapolKey->KeyInfo |= BIT(7);

    if (bMIC)
        AlignKeyInfo |= BIT(8);//EapolKey->KeyInfo |= BIT(8);

    if (bSecure)
        AlignKeyInfo |= BIT(9);//EapolKey->KeyInfo |= BIT(9);

	

    //Added by WangJS 2005.12.15
    memcpy(&EapolKey->KeyInfo, &AlignKeyInfo, sizeof(u16) );

    //CpuWord(&EapolKey->KeyInfo);
	EapolKey->KeyInfo = cpu_to_be16(EapolKey->KeyInfo);  //20061011 anson's endian
	//****************************************************
	//To fill the Key Length
	//Added by WangJS 2005.9.27
	//****************************************************
//	if(pGlobal_STA_Wpa->AuthenicationMode == WPAPSK_AUTH)
//	{
		switch(pGlobal_STA_Wpa->EncryptionMode)
		{
			case ENCRYPT_TKIP:
				//EapolKey->KeyLen = 32;
				//AlignTemp=32;
				//Added by WangJS 2006.7.14
				//AlignTemp=bPairwise?32:0;
				AlignTemp=0;
				memcpy(&EapolKey->KeyLen, &AlignTemp, sizeof(u16) );
				break;
			case ENCRYPT_CCMP:
				//EapolKey->KeyLen = 16;
				//AlignTemp=16;
				//Added by WangJS 2006.7.14
				//AlignTemp=bPairwise?16:0;
				AlignTemp=0;
				memcpy(&EapolKey->KeyLen, &AlignTemp, sizeof(u16) );
				break;
			default:
				//EapolKey->KeyLen = 0;
				AlignTemp=0;
				memcpy(&EapolKey->KeyLen, &AlignTemp, sizeof(u16) );
				break;
		}
//	}
    
    //CpuWord(&EapolKey->KeyLen);
    EapolKey->KeyLen = cpu_to_be16( EapolKey->KeyLen ); //20061011 anson's endian

    /*
	if(m_ReplayCounter == NULL)
	{
		memset(EapolKey->ReplayCounter, 0, 8);
	}
	else
	{
		m_ReplayCounter += 1;
		memcpy(EapolKey->ReplayCounter, m_ReplayCounter, 8);
	}
	*/
	//To fill the Replay count, added by WangJS 2005.9.28
	memcpy(EapolKey->ReplayCounter, (*ReplayCount), 8);
    
	memcpy(EapolKey->KeyNonce, (*KeyNonce), 32);
	
	//Added by WangJS 2005.9.29
    memcpy(EapolKey->KeyIV, (*KeyIV), 16);

	memcpy(EapolKey->KeyRSC, (*KeyRSC), 8);
	
    //EapolKey->KeyMaterialLen = (u16)KeyDataSize; //Marked by WangJS 2005.12.8
    //Added by WangJS 2005.12.8, for Alignment 
    AlignDataSize=(u16)KeyDataSize;
    memcpy(&EapolKey->KeyMaterialLen, &AlignDataSize, sizeof(u16) );
    
	//CpuWord(&EapolKey->KeyMaterialLen);
	EapolKey->KeyMaterialLen = cpu_to_be16( EapolKey->KeyMaterialLen ); //20061011 anson's endian

    if(KeyDataSize)
	{
		TotalDataSize += KeyDataSize;
		memcpy(&EapolKey[1], KeyData, KeyDataSize);
	}
	else
	{
	}

    //It is used to calculate the MIC according to MIC algorithm
	if(bMIC)
	{
		key = (*MK);
		(*MicAlgo)((u8*) EapHeader, 
			       /*BufferSize - 14, */
					TotalDataSize - sizeof(ETH_PACKET),
				   (u8*) key, 
				   16, 
				   KeyMIC);

		memcpy(EapolKey->KeyMIC, KeyMIC, 16);
	}
	else
	{
		memcpy(EapolKey->KeyMIC, (*MK), 16);
	}
	
	
	//To return the total data size
	return TotalDataSize;
}


//Added by WangJS 2005.11.11
u32 Supplicat_FillRSN(void* DeviceHandle, u8* rsn, u32 rsn_len)
{
	//unsigned char * ies = pGlobal_AP->Ies.IesData;
	//int ies_len = pGlobal_AP->Ies.IesLen;
	u8 AssociateElement[256];
	NDIS_802_11_ASSOCIATION_INFORMATION* p;
	u8* ies;
	u32 ies_len;
	
		//Added by WangJS 2005.12.6
	PWB32_ADAPTER Adapter=(PWB32_ADAPTER)DeviceHandle;

	GetRsnElement(Adapter, AssociateElement, sizeof(AssociateElement));

	//This part is responsible for get the RSN information
	p = (NDIS_802_11_ASSOCIATION_INFORMATION*) AssociateElement;

	if(!p->Length)
	{
		//No RSN Element

		return 0;
	}
	ies = AssociateElement + p->OffsetRequestIEs;
	ies_len = p->RequestIELength;
	
	
	//////////////////////////////////////////////////
	while (ies_len > 0)
	{
		//modfied by Sky 2005.4.20
		if (ies[0] == WLAN_EID_RSN_WPA || ies[0] == WLAN_EID_RSN_WPA2)
		{
            // include EID and length field
			memcpy(rsn, ies, ies[1] + 2);
			return ies[1] + 2 ;
		}
		ies_len -= ies[1] - 2;
		ies += ies[1] + 2;
	}

	return 0;
}

//-------------------------------------------------------------------------//
unsigned char KeyMICIsValid(void* DeviceHandle, PEAP_HEADER Eap, u32 Len,  Block16* MK, Block16* m_mk)
{
	
	//Added by WangJS 2005.12.6
	PWB32_ADAPTER Adapter=(PWB32_ADAPTER)DeviceHandle;
	
	Block16 KeyMic;
	u8 Buffer[1024] = {0};
	u8* key;
	

	PEAPOL_KEY EapolMessage = (PEAPOL_KEY) &Eap[1]; //marked by WangJS 2005.12.8
	

    typedef void (*MIC_ALGO)(u8 *text, u32 text_len,
               u8 *key,  u32 key_len,
               u8 *digest);

    MIC_ALGO MicAlgo=0;
        
    u16 KeyInfo = EapolMessage->KeyInfo;
    
    
    ///////////////////////////////////////////////////////////////////////////////
            
    //CpuWord(&KeyInfo);
	KeyInfo = cpu_to_be16( KeyInfo ); //20061011 anson's endian
    
	//.1)To choice the Encryption algorithm
	//************************************************************
	switch(pGlobal_STA_Wpa->EncryptionMode)
	{
		case ENCRYPT_TKIP:
			MicAlgo = hmac_md5;
		    break;
		case ENCRYPT_CCMP:
			MicAlgo = hmac_sha1;
		    break;
		default:
			break;
	}
		
/*
    if (KEY_DESC_VERSION_NUM(KeyInfo) == EAPOL_KEY_INFO_VERSION_1)
        MicAlgo = ::hmac_md5;
    else
        MicAlgo = ::hmac_sha1;
*/
	//Now, to test the TKIP encrption mode
	//MicAlgo = hmac_md5;

    //KeyMICBlock KeyMic = EapolMessage->KeyMIC;
	memcpy(KeyMic, EapolMessage->KeyMIC, sizeof(Block16) );

    OS_MEMORY_CLEAR(EapolMessage->KeyMIC, 16);

	//CpuWord(&Eap->PBL);

  

    key = (u8*)(*m_mk);

	if(MicAlgo)
	{
		(*MicAlgo)((u8*)Eap, Len, (u8*)key, 16, Buffer);
	}

	//CpuWord(&Eap->PBL);
#ifdef _WPA_PSK_DEBUG
	//For Test
	WBDEBUG(("Authenticator MIC 1\n"));
	DataDmp(KeyMic, sizeof(KeyMic), 0);

	WBDEBUG(("Generated MIC 2\n"));
	DataDmp(Buffer, sizeof(KeyMic), 0);
#endif
    //return memcmp(KeyMic, Buffer ,sizeof(KeyMic))? FALSE:TRUE;
	return OS_MEMORY_COMPARE(KeyMic, Buffer ,sizeof(KeyMic));
	
	
}

//********************************************************
// Function: To install the key into driver
// Input: STA        --> station
//		: KeyType    --> 0 : pairwise key, 1 : group key
// Added by WangJS 2005.9.29
//********************************************************
void InstallKey(void* DeviceHandle, MACAddress* STA_MAC_Address, Block16* Key1,Block16* Key2, unsigned char KeyType, u16 KeyIndex)
{
	//Added by WangJs 2005.12.6
	PWB32_ADAPTER Adapter=(PWB32_ADAPTER)DeviceHandle;
	
	AP_802_11_KEY Key;
	//NDIS_802_11_KEY Key;
	u8 *tk1, *tk2;
	OS_MEMORY_CLEAR(&Key, sizeof(AP_802_11_KEY));
#ifdef _WPA_PSK_DEBUG
	WBDEBUG(("Install Key\n"));
#endif	
	switch(pGlobal_STA_Wpa->EncryptionMode)
	{
		case ENCRYPT_TKIP:
		#ifdef _WPA_PSK_DEBUG
			WBDEBUG(("ENCRYPT_TKIP\n"));
		#endif	
			Key.KeyLength=32;
			//Key.Length=sizeof(AP_802_11_KEY) - 128 + Key.KeyLength + 10;
			if(KeyType == InstallPairwiseKey)
			{
				//pairwise key
				//tk1=(unsigned char*)STA->PMK.m_tk1;
				//tk2=(unsigned char*)STA->PMK.m_tk2;
				#ifdef _WPA_PSK_DEBUG
				WBDEBUG(("Pairwise Key\n"));
				#endif
				Key.KeyIndex = 0xC0000000 | KeyIndex;
				
			}
			else
			{
				//group key
				//tk1=(unsigned char*)STA->PMK.m_gtk1;
				//tk2=(unsigned char*)STA->PMK.m_gtk2;
				#ifdef _WPA_PSK_DEBUG
				WBDEBUG(("Group Key\n"));
				#endif
				Key.KeyIndex = 0x20000000 | KeyIndex;
			}
			
			tk1=(u8*)(*Key1);
			tk2=(u8*)(*Key2);

			memcpy(Key.KeyMaterial, tk1 ,16);
			memcpy(Key.KeyMaterial+16, tk2 ,16);
		break;
		case ENCRYPT_CCMP:
			Key.KeyLength=16;
			#ifdef _WPA_PSK_DEBUG
			WBDEBUG(("ENCRYPT_CCMP\n"));
			#endif
			//Key.Length=sizeof(AP_802_11_KEY) - 128 + Key.KeyLength + 10;
			if(KeyType == InstallPairwiseKey)
			{
				//pairwise key
				//tk1=(unsigned char*)STA->PMK.m_tk1;
				#ifdef _WPA_PSK_DEBUG
				WBDEBUG(("Pairwise Key\n"));
				#endif
				Key.KeyIndex = 0xC0000000 | KeyIndex;
				
			}
			else
			{
				//group key
				//tk1=(unsigned char*)STA->PMK.m_gtk1;
				#ifdef _WPA_PSK_DEBUG
				WBDEBUG(("Group Key\n"));
				#endif
				Key.KeyIndex = 0x20000000 | KeyIndex;
			}

			tk1=(u8*)(*Key1);
			memcpy(Key.KeyMaterial, tk1 ,16);
		break;
		default:
		break;

	}

	//According to GuildLine, the bit 28 must be set to 1
	//Key.KeyIndex |= BIT(28);
	#ifdef _WPA_PSK_DEBUG
	WBDEBUG(("Key Index=%x\n",Key.KeyIndex));
	#endif
	//To copy the MAC address of station 
	memcpy(Key.BSSID, (*STA_MAC_Address), MAC_ADDR_LENGTH);
	
	#ifdef _WPA_PSK_DEBUG
	WBDEBUG(("Install Key Bssid\n"));
	DataDmp(Key.BSSID, 6, 0);

	WBDEBUG(("Key Data =\n"));
	DataDmp(Key.KeyMaterial, Key.KeyLength,0);
	#endif
//	Key.Length=sizeof(AP_802_11_KEY) - 128 + Key.KeyLength + 10;
	SetAddKey(Adapter, &Key);


	
}

//////////////////////////////////////////////////////////////////////////////
//To check the Key Frame is "EAPoL" Frame type
//Added by WangJS 2005.9.27
//////////////////////////////////////////////////////////////////////////////
unsigned char IsEAPoL_KEY_FRAME(void* packet, u32 Len)
{
	PEAP_HEADER Eapol_Key=(PEAP_HEADER)( (u8*)packet + sizeof(ETH_PACKET) );
	

	return Eapol_Key->PT == PT_EAPOL_KEY ? TRUE : FALSE;

}

//***************************************************************************
//Get the Encryption status
//***************************************************************************
//-------------------------------------------------------------------------//
void FourWay_Get_Encryption_Status(void* DeviceHandle, u8 *EncryptStatus)
{
	PWB32_ADAPTER Adapter = (PWB32_ADAPTER)DeviceHandle;
	//u8	EncryptTmp;

	//EncryptTmp = psSME->encrypt_status;
	*EncryptStatus = psSME->encrypt_status;
	#ifdef _WPA_PSK_DEBUG
	WBDEBUG(("(WangJS)psME->encrypt_status = %d\n", psSME->encrypt_status));
	#endif
	
	/*
	if ((psSME->pairwise_key_ok != TRUE) && (psSME->group_key_ok != TRUE))
	{
		switch(EncryptTmp)
		{
			case ENCRYPT_WEP:
			case ENCRYPT_TKIP:
			case ENCRYPT_CCMP:
				*EncryptStatus = EncryptTmp + 1;	//KeyAbsent
				break;
			default:
				*EncryptStatus = EncryptTmp;
				break;
		}
	}
	else
		*EncryptStatus = EncryptTmp;
	*/
}

//***************************************************************************
//Random function
//***************************************************************************
static u32 holdrand;

void srand(u32 seed)
{
	holdrand=seed;
}

u32 rand()
{
	return (u32)( ( (holdrand=holdrand * 214013 + 2531011) >>16 ) & 0x7fff);
}


//***************************************************************************
//Cpu word swap function
//***************************************************************************


void CpuWord(u16 * w)
{
    u8 * b = (u8 *) w;
    //std::swap(b[0], b[1]);
	ByteSwap(&b[0], &b[1]);
}
 


//************************************************
//Added by WangJS 2005.9.29
//To change the Endian arrangement
//************************************************
void CpuEndian(void* Endian, u32 Size)
{
		//unsigned char* TempEndian=(unsigned char*)malloc(Size);
	//unsigned char* TempEndian=(unsigned char*)OS_MEMORY_ALLOC(Size);
	u32 i;
	u8 TempEndian[256]={0};

		for(i=0; i<Size ;i++)
			TempEndian[Size-i-1]=*( (u8*)Endian + i);
		
		memcpy(Endian, TempEndian, Size);
		//free(TempEndian);
}

//************************************************
//To compare the difference between two Bytes
//ComStr ---> 0 (">="), 1 (">"), 2 ("="), 3("<="), 4("<")
//True:  0
//False: 1
//Other: 2
//Added by WangJS 2005.11.22
//************************************************
#define CompareSize 256
u8 Compare(void* Byte1, void* Byte2, u32 ByteSize, u8 ComStr)
{

	

//	u8 CompTemp[CompareSize]={0};
	u8* B1= (u8*)Byte1;
	u8* B2= (u8*)Byte2;
	u32 count=0;
	

	if(ByteSize > CompareSize)
		return 2;
	
	
	switch(ComStr)
	{
			case 0:
				if( !OS_MEMORY_COMPARE(B1, B2, ByteSize) )
				{
					for(count=0;count<ByteSize; count++)
					{
						if(B1[count] != B2[count] )
						{
							return B1[count] > B2[count] ? (u8)0 : (u8)1;
						}
					}
				}
				else
				{
					//"=="
					return 0;
				}
				
				break;
			case 1:
				if( !OS_MEMORY_COMPARE(B1, B2, ByteSize) )
				{
					for(count=0;count<ByteSize; count++)
					{
						if(B1[count] != B2[count] )
						{
							return B1[count] > B2[count] ? (u8)0 : (u8)1;
						}
					}
				}
				else
				{
					//"=="
					return 1;
				}
					break;
			case 2:
				return !OS_MEMORY_COMPARE(B1, B2, ByteSize);
					break;
			case 3:
				
				if( !OS_MEMORY_COMPARE(B1, B2, ByteSize) )
				{
					for(count=0;count<ByteSize; count++)
					{
						if(B1[count] != B2[count] )
						{
							return B1[count] < B2[count] ? (u8)0 : (u8)1;
						}
					}
				}
				else
				{
					//"=="
					return 0;
				}
				
					break;
			case 4:
				if( !OS_MEMORY_COMPARE(B1, B2, ByteSize) )
				{
					for(count=0;count<ByteSize; count++)
					{
						if(B1[count] != B2[count] )
						{
							return B1[count] < B2[count] ? (u8)0 : (u8)1;
						}
					}
				}
				else
				{
					//"=="
					return 1;
				}
					break;
			default:
					break;
	}

	return 1;
}

//////////////////////////////////////////////////////////////////////
//To record the time of executing code
//Added by WangJS 2005.12.23
//////////////////////////////////////////////////////////////////////
void TimeStamp(void* TagString)
{
	#ifdef _WPA_PSK_TIME
	
	u32 CurrentTime;
	//OS_TIMER_GET_SYS_TIME(&CurrentTime);
	CurrentTime=jiffies;
	WBDEBUG(("(%s)CurrentTime = %d\n", (s8*)TagString,CurrentTime));
	WBDEBUG(("HZ = %d \n", HZ));
	#endif
}
//////////////////////////////////////////////////////////////////////
//Added by WangJS 2006.8.11
//To check the packet of EAPoL frame is pairwise or group key
//////////////////////////////////////////////////////////////////////
u32 CheckEAPType(void* DeviceHandle,void* RecvPacket)
{
//	PWB32_ADAPTER Adapter=(PWB32_ADAPTER)DeviceHandle;
	
	PEAPOL_KEY EapolMessage = (PEAPOL_KEY)( (u8*)RecvPacket + sizeof(ETH_PACKET) + sizeof(EAP_HEADER));
	//u32 EapolKeyFrameLength=MessageSize-sizeof(ETH_PACKET);

	
	//const u32 EapolFrameSize = sizeof(ETH_PACKET) + sizeof(EAP_HEADER) + sizeof(EAPOL_KEY) ;
								/*
								14 +	// 802.3 Protocol Type
								4 +    // 802.1x Header
								94 +    // EAPOL-Key descriptor length
								*/
	u16 KeyInfo=0;
	u32   EAPType=0;
	
	memcpy(&KeyInfo, &EapolMessage->KeyInfo, sizeof(KeyInfo));
	#ifdef _WPA_PSK_DEBUG
	WBDEBUG(("CheckEAPType -- (1)KeyInfo=%x\n",KeyInfo));
	#endif
	
	//CpuWord(&KeyInfo);
	KeyInfo = be16_to_cpu( KeyInfo ); //20061011 anson's endian
	
	#ifdef _WPA_PSK_DEBUG
	WBDEBUG(("CheckEAPType -- (2)KeyInfo=%x\n",KeyInfo));
	#endif
	
	EAPType=(KeyInfo&BIT(3))?PAIRWISE_FRAME_TYPE:GROUP_FRAME_TYPE;
	
	if(EAPType==PAIRWISE_FRAME_TYPE)
		WBDEBUG(("PAIRWISE_FRAME_TYPE\n"));
	else	
		WBDEBUG(("GROUP_FRAME_TYPE\n"));
	
	return EAPType;
}

//////////////////////////////////////////////////////////////////////
//To Conver the character to Digital number
//Added by WangJS 2006.8.17
//////////////////////////////////////////////////////////////////////
u8 CharToBin(u8 Character)
{
	u8 BinaryData=0x00;
	
	//WBDEBUG(("Character =%x\n",Character));
	if(( (Character>='a') &&  (Character<='f') ) ||
		( (Character>='A') &&  (Character<='F') ) )
	{
		BinaryData=(Character&0x0f)+0x9;
		//WBDEBUG(("Binary Data =%x\n",BinaryData));
		return BinaryData;
	}
		
	if( (Character>='0') &&  (Character<='9'))
	{
		BinaryData=(Character&0x0f);
		//WBDEBUG(("Binary Data =%x \n",BinaryData));
		return BinaryData;
	}
	
   return BinaryData;
}


